package com.youxin.chat.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CreateCache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youxin.base.BaseResultCode;
import com.youxin.base.MsgDto;
import com.youxin.chat.basic.dto.constant.FileTypeEnum;
import com.youxin.chat.user.manager.UserManager;
import com.youxin.common.constant.MqConstant;
import com.youxin.common.constant.MsgTypeEnum;
import com.youxin.chat.user.enums.FriendStatusEnum;
import com.youxin.chat.user.enums.UserSourceEnum;
import com.youxin.chat.user.manager.ImManager;
import com.youxin.chat.user.manager.UserFriendManager;
import com.youxin.chat.user.mapper.UserAddMapper;
import com.youxin.chat.user.mapper.UserFriendMapper;
import com.youxin.chat.user.mapper.UserInfoMapper;
import com.youxin.chat.user.model.UserAdd;
import com.youxin.chat.user.model.UserFriend;
import com.youxin.chat.user.model.UserInfo;
import com.youxin.chat.user.rpc.FileService;
import com.youxin.chat.user.service.UserFriendService;
import com.youxin.chat.user.vo.req.FriendDisturbReq;
import com.youxin.chat.user.vo.req.UserApplyReq;
import com.youxin.chat.user.vo.user.UserFriendVo;
import com.youxin.chat.user.vo.user.UserSearchVo;
import com.youxin.exception.SystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import static com.youxin.common.constant.MqConstant.TOPIC_EXCHANGE;

/**
 * description: UserFriendServiceImpl <br>
 * date: 2020/2/25 14:12 <br>
 * author: llkj <br>
 * version: 1.0 <br>
 */
@Service
public class UserFriendServiceImpl extends ServiceImpl<UserFriendMapper, UserFriend> implements UserFriendService {

    private static final Logger logger = LoggerFactory.getLogger(UserFriendServiceImpl.class);

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private UserAddMapper userAddMapper;

    @Resource
    private UserFriendManager userFriendManager;

    @Resource
    private ImManager imManager;

    @Resource
    private AmqpTemplate amqpTemplate;

    @Resource
    private FileService fileService;

    @Resource
    private UserManager userManager;

    @CreateCache(name = "user.friend.list.")
    private Cache<String, Object> jetcache;

    @Override
    public void applyUser(String userNo, UserApplyReq userApplyReq) throws SystemException {
        UserInfo userInfo = userManager.selectByUserNo(userNo);
        UserInfo applyUserInfo = userManager.selectByUserNo(userApplyReq.getUserNo());
        if (applyUserInfo == null || userInfo == null) {
            logger.error("获取用户信息失败，userNo={},data={}", userNo, JSONObject.toJSONString(userApplyReq));
            throw new SystemException(BaseResultCode.RECORD_NOT_EXISTS, "系统内部异常，请联系技术人员");
        }
        if (userNo.equalsIgnoreCase(userApplyReq.getUserNo())) {
            logger.error("不允许添加本人为好友，userNo={},data={}", userNo, JSONObject.toJSONString(userApplyReq));
            throw new SystemException(BaseResultCode.RECORD_EXISTS, "不允许添加本人为好友");
        }
        if (Integer.compare(UserSourceEnum.MOBILE.getSource(), userApplyReq.getSource()) == 0) {
            if (StringUtils.isEmpty(userApplyReq.getMobile()) || !userApplyReq.getMobile().equals(applyUserInfo.getMobile())) {
                logger.error("申请添加人的用户手机号与传入的不一致，userNo={},applyMobile={},,mobile={}", userApplyReq.getUserNo(), userApplyReq.getMobile(), applyUserInfo.getMobile());
                throw new SystemException(BaseResultCode.SECURITY_ERROR, "申请添加人的用户手机号与传入的不一致");
            }
        }
        int count = userAddMapper.selectCount(new LambdaQueryWrapper<UserAdd>().eq(UserAdd::getUserNo, userNo).eq(UserAdd::getAddUserNo, userApplyReq.getUserNo()).eq(UserAdd::getAddStatus, 0));
        if (count > 0) {
            logger.error("用户已经申请，无须再度申请,userNo={},userAddNo={}", userNo, userApplyReq.getUserNo());
            return;
        }
        UserFriend userFriend = this.baseMapper.selectFriendDetails(userNo, userApplyReq.getUserNo());
        if (userFriend != null) {
            logger.error("该用户在好友列表中已存在,userNo={},userAddNo={}", userNo, userApplyReq.getUserNo());
            throw new SystemException(BaseResultCode.RECORD_EXISTS, "该用户在好友列表中已存在");
        }


        UserAdd userAdd = new UserAdd();
        userAdd.setNickName(userInfo.getNickName());
        userAdd.setAvatar(userInfo.getAvatar());
        userAdd.setAddNickName(applyUserInfo.getNickName());
        userAdd.setAddAvatar(applyUserInfo.getAvatar());
        userAdd.setUserNo(userNo);
        userAdd.setAddUserNo(userApplyReq.getUserNo());
        userAdd.setAddSource(userApplyReq.getSource());
        userAdd.setAddTime(LocalDateTime.now());
        userAdd.setRemark(userApplyReq.getRemark());
        userAdd.setCreateTime(LocalDateTime.now());
        userAdd.setUpdateTime(LocalDateTime.now());
        userAdd.setAddStatus(0);
        userAdd.setDeviceType(userApplyReq.getDeviceType());
        userAddMapper.insert(userAdd);
    }

    @Override
    public void handleApply(String userNo, String applyUserNo, Integer action) throws SystemException {
        UserAdd userAdd = userAddMapper.selectOne(new LambdaQueryWrapper<UserAdd>().eq(UserAdd::getAddUserNo, userNo).eq(UserAdd::getUserNo, applyUserNo).eq(UserAdd::getAddStatus, 0));
        if (userAdd == null) {
            logger.error("获取申请用户信息失败，userNo={},applyUserNo={}", userNo, applyUserNo);
            throw new SystemException(BaseResultCode.RECORD_NOT_EXISTS, "该记录不存在或已审批");
        }
        userAdd.setAddStatus(action);
        if (action == -1) {
            userAddMapper.updateById(userAdd);
        }
        else if (action == 1) {
            List<Integer> result = userFriendManager.addFriend(userNo, applyUserNo, action);
            if (result.contains(0)) {
                imManager.addWhiteList(userNo, Arrays.asList(applyUserNo));
            }
            if (result.contains(1)) {
                imManager.addWhiteList(applyUserNo, Arrays.asList(userNo));
            }
        }
        amqpTemplate.convertAndSend(TOPIC_EXCHANGE,"msg.user", new MsgDto(MsgTypeEnum.USER_APPLY.getType(), userAdd));
    }

    @Override
    public UserSearchVo findUserByKey(String userNo, String searchKey) throws SystemException {
        UserSearchVo searchResult = userInfoMapper.selectUserByUserName(searchKey);
        if (searchResult == null) {
            searchResult = userInfoMapper.selectUserByMobile(searchKey);
        }
        if (searchResult == null) {
            throw new SystemException(BaseResultCode.RECORD_NOT_EXISTS, "搜索的用户不存在");
        }
        searchResult.setIsFriend(0);
        if (searchResult != null) {
            int count = this.baseMapper.selectCount(new LambdaQueryWrapper<UserFriend>().eq(UserFriend::getUserNo, userNo).eq(UserFriend::getFriendNo, searchResult.getUserNo()));
            if (count > 0) {
                searchResult.setIsFriend(1);
            }
            searchResult.setAvatar(fileService.getImageUrl(FileTypeEnum.USER_AVATAR.getType(), searchResult.getAvatar()));
        }
        return searchResult;
    }

    @Override
    public List<UserFriendVo> listFriend(String userNo) throws SystemException {

        List<UserFriendVo> list = userFriendManager.listFriend(userNo);
        list.stream().forEach(item -> {
            item.setFriendAvatar(fileService.getImageUrl(FileTypeEnum.USER_AVATAR.getType(), item.getFriendAvatar()));
        });
        return list;
    }

    @Override
    public UserFriendVo selectFriendDetails(String userNo, String friendNo) throws SystemException {
        UserFriend userFriend = this.baseMapper.selectFriendDetails(userNo, friendNo);
        if (userFriend == null) {
            throw new SystemException(BaseResultCode.RECORD_NOT_EXISTS, "该用户不是当前用户的好友");
        }
        UserInfo userInfo = userManager.selectByUserNo(friendNo);
        UserFriendVo userFriendDto = new UserFriendVo();
        userFriendDto.setUserNo(userFriend.getUserNo());
        userFriendDto.setFriendNo(userFriend.getFriendNo());
        userFriendDto.setFriendAvatar(fileService.getImageUrl(FileTypeEnum.USER_AVATAR.getType(), userFriend.getFriendAvatar()));
        userFriendDto.setFriendNickName(userFriend.getFriendNickName());
        userFriendDto.setFriendNote(userFriend.getFriendNote());
        userFriendDto.setFriendStatus(userFriend.getFriendStatus());
        userFriendDto.setCreateTime(userFriend.getCreateTime());
        userFriendDto.setUpdateTime(userFriend.getUpdateTime());
        userFriendDto.setNickName(userFriend.getFriendNickName());
        userFriendDto.setSex(userInfo.getSex());
        userFriendDto.setArea(userInfo.getArea());
        userFriendDto.setStarFriend(userFriend.getStarFriend());
        userFriendDto.setNotDisturb(userFriend.getNotDisturb());
        userFriendDto.setFriendNote(userFriend.getFriendNote());
        userFriendDto.setClearTime(Optional.ofNullable(userFriend.getExt()).map(JSONObject::parseObject).map(item->item.getInteger("clearTime")).orElse(-1));
        userFriendDto.setPrintScreenNotify(Optional.ofNullable(userFriend.getExt()).map(JSONObject::parseObject).map(item->item.getInteger("printScreenNotify")).orElse(0));
        userFriendDto.setClearTimePoint(Optional.ofNullable(userFriend.getExt()).map(JSONObject::parseObject).map(item->item.getString("clearTimePoint")).orElse(""));
        return userFriendDto;
    }

    @Override
    public void blackUser(String userNo, String friendNo, Integer status) throws SystemException {
        if (!FriendStatusEnum.BLACK.getStatus().equals(status) && !FriendStatusEnum.NORMAL.getStatus().equals(status)) {
            throw new SystemException(BaseResultCode.COMMON_FAIL, "状态必须是正常或拉黑状态");
        }
        if (FriendStatusEnum.BLACK.getStatus().equals(status)) {
            imManager.removeWhiteList(userNo, Arrays.asList(friendNo));
        } else {
            imManager.addWhiteList(userNo, Arrays.asList(friendNo));
        }
        UserFriend userFriend = new UserFriend();
        userFriend.setFriendStatus(status);
        this.baseMapper.update(userFriend, new LambdaQueryWrapper<UserFriend>().eq(UserFriend::getUserNo, userNo).eq(UserFriend::getFriendNo, friendNo));
    }

    @Override
    public void deleteFriend(String userNo, String friendNo) throws SystemException {
        imManager.removeWhiteList(userNo, Arrays.asList(friendNo));
        imManager.removeWhiteList(friendNo, Arrays.asList(userNo));
        userFriendManager.deleteFriend(userNo, friendNo);
    }

    @Override
    public void starFriend(String userNo, String friendNo, Integer type) throws SystemException {
        UserFriend userFriend = new UserFriend();
        userFriend.setStarFriend(type);
        userFriend.setUserNo(userNo);
        userFriend.setFriendNo(friendNo);
        userFriendManager.starFriend(userFriend);
    }

    @Override
    public void remarkFriend(String userNo, String friendNo, String remark) throws SystemException {
        UserFriend userFriend = new UserFriend();
        userFriend.setFriendNote(remark);
        userFriend.setUserNo(userNo);
        userFriend.setFriendNo(friendNo);
        userFriendManager.remarkFriend(userFriend);
    }

    @Override
    public void setFriendDisturb(String userNO, FriendDisturbReq friendDisturbDto) throws SystemException {
        this.baseMapper.setFriendDisturb(userNO, friendDisturbDto.getType(),friendDisturbDto.getFriendId());
        imManager.setFriendDisturb(userNO, friendDisturbDto.getFriendId(), friendDisturbDto.getType());
    }

    @Override
    public List<UserFriendVo> blackList(String userNo) throws SystemException {
        List<UserFriendVo> list = this.baseMapper.blackList(userNo);
        list.stream().forEach(item -> item.setFriendAvatar(fileService.getImageUrl(FileTypeEnum.USER_AVATAR.getType(), item.getFriendAvatar())));
        return list;
    }


}
